package org.concordia.wsdl.evaluator;

import java.util.LinkedList;
import java.util.List;

import org.concordia.wsdl.helper.ListUtils;
import org.concordia.wsdl.helper.CompositionUtils;
import org.concordia.wsdl.model.WebService;

public class RevisedLookaheadBFStarEvaluator implements Evaluator {

	private List<WebService> children;
	
	public float evaluate(WebService candidate, List<String> rOut,
			List<String> knownParams, List<WebService> invokedWSList,
			List<WebService> remainingWSList, List<WebService> candidates) {

		
		WebService child;
		children = CompositionUtils.getCandidates(remainingWSList, candidate, knownParams);
		List<WebService> candidateWrapper = new LinkedList<WebService>();
		candidateWrapper.add(candidate);

		
		child = this.getBestChild(children, rOut, ListUtils.union(knownParams,candidate.getOutputs()),
				ListUtils.unionWS(invokedWSList, candidateWrapper),
				ListUtils.subWS(remainingWSList, candidateWrapper),
				candidates);
		
		float sum;
		float gScore = invokedWSList.size();
		float hScore;
		
		List<String> remainingParams = ListUtils.sub(rOut, knownParams);
		List<String> joinList;
		if(child != null){
			joinList = ListUtils.join(remainingParams, 
					ListUtils.union(ListUtils.union(knownParams,candidate.getOutputs()), 
							child.getOutputs()));		
		}else{
			joinList = ListUtils.join(remainingParams, ListUtils.union(knownParams,candidate.getOutputs()));			
		}

		if(joinList.size() == 0){
			hScore = 2;
		}else{
			hScore = 1 / joinList.size();		
		}
		sum = hScore + gScore;
		candidate.setScore(sum);
		return sum;	
	}
	
	private WebService getBestChild(List<WebService> children, List<String> rOut,
			List<String> knownParams, List<WebService> invokedWSList,
			List<WebService> remainingWSList, List<WebService> candidates){
		
		WebService best = null;
		float bestScore = 10000 * 10000;
		
		for(WebService c : children){
	
			float sum;
			float gScore = invokedWSList.size();
			float hScore;
			List<String> remainingParams = ListUtils.sub(rOut, knownParams);
			List<String> joinList = ListUtils.join(remainingParams, 
					ListUtils.union(knownParams, c.getOutputs()));
			if(joinList.size() == 0){
				hScore = 2;
			}else{
				hScore = 1 / joinList.size();		
			}
			sum = hScore + gScore;
			if(bestScore > sum & !candidates.contains(c)){
				bestScore = sum;
				best = c;
			}
			
		}

		return best;
	}



}
